﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Garlic.CC.Utility;

namespace Garlic.CC.BaseClass
{
    /// <summary>
    /// 页面的基类。 所有显示给用户的页面必须从此界面进行继承。
    /// </summary>
    public class BasePage : System.Web.UI.Page
    {
        public const string SessionKey_CurrentUser = "SessionKey_CurrentUser";
        public const string PostBackControlID = "lbPostBack";

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (this.Request.Url.AbsoluteUri.IndexOf("Default.aspx") < 0)
            {
                if (this.CurrentUser == null)
                {
                    this.Response.Redirect("~/Default.aspx");
                }
            }
        }
        /// <summary>
        /// 当前用户
        /// </summary>
        public IUser CurrentUser
        {
            get
            {
                try
                {
                    if (Session[BasePage.SessionKey_CurrentUser] == null)
                    {
                        throw new Garlic.CC.Utility.AuthenticationException();
                    }
                    return (IUser)Session[SessionKey_CurrentUser];
                }
                catch (HttpException)
                {
                    return null;
                }
            }
            set
            {
                Session[SessionKey_CurrentUser] = value;
            }
        }

        /// <summary>
        /// 向页面输出javascript
        /// </summary>
        /// <param name="key"></param>
        /// <param name="script"></param>
        /// <returns></returns>
        public void RegisterJS(string key, string script)
        {
            if (!ClientScript.IsStartupScriptRegistered(key))
            {
                ClientScript.RegisterStartupScript(this.GetType(), key, script);
            }
        }

        /// <summary>
        /// 处理页面异常
        /// </summary>
        /// <param name="ex"></param>
        public void HandleException(Exception ex)
        {
            try
            {
                //这里统一处理异常，如果是需要特别处理的异常，例如需要重新尝试事务，均可在这里处理
                if (ex is MPSBusinessException)
                {
                    MPSBusinessException bEx = (MPSBusinessException)ex;
                    this.Message = bEx.Message;
                }
                else if (ex is AuthenticationException)
                {
                    Server.Transfer("~/Default.aspx");
                }
                else if (ex is System.Threading.ThreadAbortException || ex is System.Web.HttpException)
                {
                    // 如果是页面跳转时终止线程异常，则不再做任何处理, remove loginfo for release version
                    // Logger.LogInfo("Garlic.CC.BaseClass", "HandleException", "BasePage", ex.ToString());                    
                }
                else if (ex is System.Data.SqlClient.SqlException && ex.Message.StartsWith("Invalid column name"))
                {
                    //日志 Logger.LogError("Garlic.CC.BaseClass", "HandleException", "BasePage", "数据库异常", ex);
                    this.Message = ex.Message.Replace("Invalid column name", "系统遇到了一个无法处理的多余数据列：");
                }
                else
                {
                    //日志 Logger.LogError("Garlic.CC.BaseClass", "HandleException", "BasePage", "页面处理异常", ex);
                    this.Message = ex.Message;
                }
            }
            catch (Exception e)
            {
                try
                {
                    if (e is System.Threading.ThreadAbortException || e is System.Web.HttpException)
                    {
                        // 如果是页面跳转时终止线程异常，则不再做任何处理, remove loginfo for release version
                        //日志 Logger.LogInfo("Garlic.CC.BaseClass", "HandleException", "BasePage", ex.ToString());                    
                    }
                    else
                    { } //日志Logger.LogError("Garlic.CC.BaseClass", "HandleException", "BasePage", "错误处理异常", e);}
                }
                catch { }
            }
        }

        private string _message;
        /// <summary>
        /// 向用户显示信息提示
        /// </summary>
        public String Message
        {
            get { return _message; }
            set
            {
                _message = value;
            }
        }
        /// <summary>
        /// 检查是否有特定的权限
        /// </summary>
        /// <param name="sec">安全选项</param>
        /// <returns></returns>
        public bool CheckPermissionSuccess()
        {
            if (this.CurrentUser == null)
                return false;
            return true;
        }
        ///<summary>
        /// 页最顶端的PlaceHolder
        /// </summary>
        public System.Web.UI.WebControls.PlaceHolder plhTopHolder;
        public System.Web.UI.WebControls.PlaceHolder plhBottomHolder;
        /// <summary>
        /// 页面初始化
        /// </summary>
        /// <param name="e"></param>
        protected override void OnInit(EventArgs e)
        {
            //event
            this.Error += new EventHandler(BasePage_Error);
            this.PreRender += new EventHandler(BasePage_PreRender);

            base.OnInit(e);
        }
        /// <summary>
        /// 对服务器端生成的控件不做正确性验证，以免自定义render失败
        /// </summary>
        /// <param name="control"></param>
        public override void VerifyRenderingInServerForm(Control control)
        {
            //base.VerifyRenderingInServerForm(control);
        }

        /// <summary>
        /// 页面发生错误
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BasePage_Error(object sender, EventArgs e)
        {
            Exception ex = Server.GetLastError();
            this.HandleException(ex);
        }

        /// <summary>
        /// 页面预呈现
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BasePage_PreRender(object sender, EventArgs e)
        {
            this.IsRefreshPage = false;

            //注册消息框
            this.RegisterMessageBox();
            //注册隐藏控件
            this.RegisterHiddenBox();

        }

        protected override void CreateChildControls()
        {
            //注册页面回发linkbutton
            this.RegisterPostBackLinkButton();
            base.CreateChildControls();

        }
        /// <summary>
        /// //向每个页面注册一个隐藏的控件，用作界面上公共存储区，该存储区内的数据格式必须
        ///遵循如下格式：key,value;key,value;
        ///界面层可以使用javascript向该控件赋值 。调用SetServerValue();
        /// </summary>
        private void RegisterHiddenBox()
        {
            string js = "<script language='javascript'>"
            + "function SetShareStore(key,value)"
            + " {var serverValue = document.getElementById('__ShareStore').value;"
            + "   serverValue += key+','+value+';'}"
            + "</script>";

            ClientScript.RegisterHiddenField("__ShareStore", "");

            this.RegisterJS("SetServerValue", js);
        }

        protected void SetShareStore(string key, string value)
        {
            //to do...
        }

        /// <summary>
        /// 是否服务端刷新页面
        /// 该属性是一次性的使用，每次页面呈现之前该值会被置为false
        /// </summary>
        public bool IsRefreshPage
        {
            get
            {
                if (ViewState["BasePage_IsRefreshPage"] == null)
                    ViewState["BasePage_IsRefreshPage"] = false;
                return (bool)ViewState["BasePage_IsRefreshPage"];
            }
            set
            {
                ViewState["BasePage_IsRefreshPage"] = value;
            }
        }

        /// <summary>
        /// 获取客户端赋予的服务端变量值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        protected string GetShareStore(string key)
        {
            string serverValue = Request.Form["__ShareStore"].ToString();
            if (string.IsNullOrEmpty(serverValue)) return "";
            if (serverValue.IndexOf(',') < 0) return "";
            if (serverValue.IndexOf(';') < 0) serverValue += ";";

            string[] keyValues = serverValue.Split(';');
            foreach (string keyValue in keyValues)
            {
                if (key == keyValue.Split(',')[0])
                    return keyValue.Split(',')[1];
            }
            return "";
        }

        /// <summary>
        /// 通过后台代码设置web界面上的html控件的可见性
        /// </summary>
        /// <param name="elementID"></param>
        /// <param name="visible"></param>
        protected void SetClientElementVisible(string elementID, bool visible)
        {
            string js = "<script language='javascript'>"
            + " SetClientElementVisible('" + elementID + "'," + visible + ");"
            + "</script>";

            this.RegisterJS("SetClientElementVisible", js);
        }

        /// <summary>
        /// 注册页面消息框
        /// </summary>
        private void RegisterMessageBox()
        {
            if (this.GetMasterForm() == null) return;
            if (this.GetMasterForm().FindControl("pnlMessage") == null) return;
            ((Panel)(this.GetMasterForm().FindControl("pnlMessage"))).Visible = false;
            if (!string.IsNullOrEmpty(Request.Form["__ShareStore"]))
            {
                this.Message = Request.Form["__ShareStore"];
            }
            //添加信息提示
            if (!string.IsNullOrEmpty(this.Message))
            {
                ((Panel)(this.GetMasterForm().FindControl("pnlMessage"))).Visible = true;
                ((Label)(this.GetMasterForm().FindControl("lblMessage"))).Text = this.Message;
            }

        }

        private HtmlForm GetMasterForm()
        {
            if (this.Master != null)
            {
                HtmlForm form = (HtmlForm)(this.Master.FindControl("Form1"));
                return form;
            }
            return null;
        }

        /// <summary>
        ///向页面注册一个linkbutton，留作页面刷新回发使用
        /// </summary>
        private void RegisterPostBackLinkButton()
        {
            if (this.GetMasterForm() == null) return;

            PlaceHolder plhTop = (PlaceHolder)(this.GetMasterForm().FindControl("plhTopContainer"));
            if (plhTop == null) return;

            LinkButton lb = new LinkButton();
            lb.ID = BasePage.PostBackControlID;
            lb.Text = "";
            lb.Click += new EventHandler(PostBack_Click);
            plhTop.Controls.Add(lb);
        }

        protected void PostBack_Click(object sender, EventArgs e)
        {
            OnReFreshPostBack();
        }

        /// <summary>
        /// 当postback控件触发回发后，子类需要重写该方法才能实现页面回发刷新效果。
        /// 比如可以调用search方法来实现重新查询
        /// </summary>
        protected virtual void OnReFreshPostBack()
        {
        }

        /// <summary>
        /// 关闭当前虚拟窗口
        /// 如果当前窗口是使用window.open()的方式弹出的系统内置窗口
        /// 则不适用该方法
        /// </summary>
        /// <param name="isRefreshPage">是否需要刷新父页面</param>
        protected void CloseVirtualWindow(bool needRefreshPage)
        {
            if (needRefreshPage)
            {
                LinkButton lb = (LinkButton)(this.GetMasterForm().FindControl(BasePage.PostBackControlID));
                if (lb != null)
                {
                    //直接调用父页面回发js函数，进行postback即可
                    string strScript = "<script language='javascript'>"
                    + "window.parent.$('__ShareStore').value = '" + this.Message + "';"//将子页面的消息通过隐藏控件传递到父页
                    + "window.parent.Base_PostBack('" + lb.ClientID + "');"
                    + "</script>";
                    this.RegisterJS("Base_PostBack_JS", strScript);
                }
            }
            else
            {
                string strScript = "<script language='javascript'>"
                + "window.parent.CloseVirtualWindow();"
                + "</script>";
                this.RegisterJS("Base_CloseWindow_JS", strScript);
            }
        }

        public new void SetFocus(string clientID)
        {
            string script = "<script language='javascript'>SetFocus('" + clientID + "');</script>";
            this.RegisterJS("BasePage_SetFocus", script);
        }

        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="context"></param>
        public void DownLoadFile(string fileName, bool isWebPath)
        {
            if (isWebPath)
                fileName = Server.MapPath(fileName);
            string realFileName = fileName.Substring(fileName.LastIndexOf('\\') + 1);
            HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=" + HttpUtility.UrlEncode(realFileName));
            //HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312");
            //HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";
            HttpContext.Current.Response.ContentType = "text/csv";
            HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.Unicode;
            HttpContext.Current.Response.TransmitFile(fileName);
            // HttpContext.Current.Response.Flush();
            HttpContext.Current.Response.End();
        }

        #region async handler

        protected string OutputFilePath
        {
            set
            {
                //ScriptManager.RegisterStartupScript(this.Panel1, typeof(UpdatePanel), "downloadfile", string.Format("window.open('{0}');", value), true);
                //ScriptManager.RegisterStartupScript(this, typeof(BasePage), "downloadfile", string.Format("window.location.href='{0}';", value), true);

                DownLoadFile(value, true);
            }
        }

        protected string Information
        {
            set
            {
                ScriptManager.RegisterClientScriptBlock(this, typeof(BasePage), "showMessage",
                                                        string.Format(
                                                            "$get('InfoDiv').style.display = 'block';$get('InfoMessage').innerHTML='{0}';",
                                                            value), true);
            }
        }

        #endregion
    }
}